﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Core
{
    public static partial class user
    {
        public static dynamic getUserCompare(string usernameA, string usernameB, string username)
        {
            var sql = new Sql.SqlDataContext();
            var ua = sql.User.FirstOrDefault(row => row.username.ToLower() == usernameA.ToLower());
            if (ua == null) return new
                {
                    success = false,
                    msg = "用户A不存在"
                };
            var ub = sql.User.FirstOrDefault(row => row.username.ToLower() == usernameB.ToLower());
            if (ub == null) return new
            {
                success = false,
                msg = "用户B不存在"
            };
            var onlyAAccept = from soa in sql.Solve
                              where soa.username == ua.username && soa.accept > 0 &&
                                    !sql.Solve.Any(sob => sob.username == ub.username && sob.pid == soa.pid && sob.accept > 0)
                              from s in sql.Status
                              from p in sql.Problem
                              from l in sql.Language
                              where s.rid == soa.bestRid && p.pid == soa.pid && l.code == s.lang
                              orderby soa.pid
                              select new
                              {
                                  s.rid,
                                  soa.pid,
                                  problemTitle = p.title,
                                  soa.accept,
                                  soa.submit,
                                  s.exeTime,
                                  s.exeMem,
                                  codeLen = s.code.Length,
                                  allowCode = ua.username == username,
                                  lang = l.title,
                                  langCode = s.lang
                              };
            var onlyBAccept = from sob in sql.Solve
                              where sob.username == ub.username && sob.accept > 0 &&
                                    !sql.Solve.Any(soa => soa.username == ua.username && soa.pid == sob.pid && soa.accept > 0)
                              from s in sql.Status
                              from p in sql.Problem
                              from l in sql.Language
                              where s.rid == sob.bestRid && p.pid == sob.pid && l.code == s.lang
                              orderby sob.pid
                              select new
                              {
                                  s.rid,
                                  sob.pid,
                                  problemTitle = p.title,
                                  sob.accept,
                                  sob.submit,
                                  s.exeTime,
                                  s.exeMem,
                                  codeLen = s.code.Length,
                                  allowCode = ub.username == username,
                                  lang = l.title,
                                  langCode = s.lang
                              };
            var bothAccept = from soa in sql.Solve
                             from sob in sql.Solve
                             where soa.pid == sob.pid &&
                                   soa.username == ua.username && soa.accept > 0 &&
                                   sob.username == ub.username && sob.accept > 0
                             from sa in sql.Status
                             from sb in sql.Status
                             where sa.rid == soa.bestRid && sb.rid == sob.bestRid
                             let winner = sa.exeTime < sb.exeTime ||
                                          sa.exeTime == sb.exeTime && (sa.exeMem < sb.exeMem ||
                                          sa.exeMem == sb.exeMem && (sa.code.Length < sb.code.Length ||
                                          sa.code.Length == sb.code.Length && sa.submitTime < sb.submitTime))
                                          ? ua.username : ub.username
                             let s = winner == ua.username ? sa : sb
                             let so = winner == ua.username ? soa : sob
                             from p in sql.Problem
                             from l in sql.Language
                             where p.pid == s.pid && l.code == s.lang
                             orderby s.pid
                             select new
                             {
                                 winner,
                                 s.rid,
                                 s.pid,
                                 problemTitle = p.title,
                                 so.accept,
                                 so.submit,
                                 s.exeTime,
                                 s.exeMem,
                                 codeLen = s.code.Length,
                                 allowCode = winner == username,
                                 lang = l.title,
                                 langCode = s.lang
                             };
            var onlyAFail = from soa in sql.Solve
                            where soa.username == ua.username && soa.accept == 0 && soa.submit > 0 &&
                                  !sql.Solve.Any(sob => sob.username == ub.username && sob.pid == soa.pid && sob.submit > 0)
                            from p in sql.Problem
                            where p.pid == soa.pid
                            orderby soa.pid
                            select new
                            {
                                soa.pid,
                                problemTitle = p.title,
                                soa.submit
                            };
            var onlyBFail = from sob in sql.Solve
                            where sob.username == ub.username && sob.accept == 0 && sob.submit > 0 &&
                                  !sql.Solve.Any(soa => soa.username == ua.username && soa.pid == sob.pid && soa.submit > 0)
                            from p in sql.Problem
                            where p.pid == sob.pid
                            orderby sob.pid
                            select new
                            {
                                sob.pid,
                                problemTitle = p.title,
                                sob.submit
                            };
            var bothFail = from soa in sql.Solve
                           from sob in sql.Solve
                           where soa.pid == sob.pid &&
                                 soa.username == ua.username && sob.username == ub.username &&
                                 soa.accept == 0 && soa.submit > 0 &&
                                 sob.accept == 0 && sob.submit > 0
                           from p in sql.Problem
                           where p.pid == soa.pid
                           orderby p.pid
                           select new
                           {
                               p.pid,
                               problemTitle = p.title,
                               submitA = soa.submit,
                               submitB = sob.submit
                           };
            return new
            {
                success = true,
                usernameA = ua.username,
                usernameB = ub.username,
                nicknameA = ua.nickname,
                nicknameB = ub.nickname,
                onlyAAccept,
                onlyBAccept,
                bothAccept,
                onlyAFail,
                onlyBFail,
                bothFail
            };
        }
    }
}
